#pragma once

// class declarations
class CogCache;

// -----

#include "CogBase.h"
#include "CogObjective.h"

#include <boost/pool/pool.hpp>

// ------------------------------------------------------------------------------------------

class CogCache
{
public:
	CogCache() : pPool(NULL) {}
	~CogCache() { clear(); }

	void create(CogMultiObjective* pObjectives);
	void clear();
	bool hasStorage() { return pPool ? true : false; }

	char* allocate();
	void destroy(char* pData);

private:
	boost::pool<>* pPool;
	vector<CogEvaluator*> evaluators;
};

// -----

inline
void CogCache::create(CogMultiObjective* pObjectives)
{
	size_t offset = 0;
	for (size_t i = 0; i < pObjectives->stages(); i++)
	{
		for (size_t j = 0; j < pObjectives->stageSize(i); j++)
		{
			CogEvaluator* pEval = pObjectives->objectiveEvaluator(i, j);
			size_t updated = pEval->setCacheOffset(offset);
			if (updated != offset)
			{
				offset = updated;
				evaluators.push_back(pEval);
			}
		}
	}
	if (offset)
	{
		pPool = new boost::pool<>(offset);
	}
}

inline
void CogCache::clear() 
{ 
	delete pPool; 
	pPool = NULL; 
	evaluators.clear(); 
}

inline
char* CogCache::allocate() 
{ 
	char* pData = static_cast<char*>(pPool->malloc());
	for (size_t i = 0; i < evaluators.size(); i++)
	{
		evaluators[i]->constructCache(pData+evaluators[i]->getCacheOffset());
	}
	return pData;
}

inline
void CogCache::destroy(char* pData) 
{ 
	for (size_t i = 0; i < evaluators.size(); i++)
	{
		evaluators[i]->destroyCache(pData+evaluators[i]->getCacheOffset());
	}
	pPool->free(pData); 
}

// ------------------------------------------------------------------------------------------